package com.hit.client.comm;

import cn.hutool.core.thread.ThreadUtil;
import com.hit.comm.constants.CommConstants;
import com.hit.comm.netty.MessageDecoder;
import com.hit.comm.netty.MessageEncoder;
import com.hit.comm.netty.TcpClient;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;


@Slf4j
public class NettyClient {

    // 全局唯一的 NettyClient 实例
    private static volatile NettyClient instance;

    // 连接相关的字段
    public static String host = "";
    public static int port = 9876;
    public static TcpClient tcpClient;

    // 私有构造方法，确保外部无法直接创建实例
    private NettyClient() {

    }

    // 获取唯一实例，双重检查锁定确保线程安全
    public static NettyClient getInstance() {
        if (instance == null) {
            synchronized (NettyClient.class) {
                if (instance == null) {
                    instance = new NettyClient();
                }
            }
        }
        return instance;
    }

    // 启动连接并带有重连机制
    public void connect(String host, int port) {
        if (Objects.equals(NettyClient.host,host) && Objects.equals(NettyClient.port,port) && tcpClient!=null){
            log.info("tcp client already exist");
            return;
        }
        if (tcpClient!=null){
            try {
                tcpClient.shutdown();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        NettyClient.host = host;
        NettyClient.port = port;
        tcpClient = new TcpClient("robot-client-comm", host ,port, new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                ByteBuf delimiter = Unpooled.copiedBuffer(CommConstants.DELIMITER.getBytes());
                channel.pipeline().addLast(new DelimiterBasedFrameDecoder(CommConstants.MAX_LENGTH, delimiter));
                channel.pipeline().addLast(new MessageDecoder());
                channel.pipeline().addLast(new MessageEncoder());
                channel.pipeline().addLast(new NettyClientHandler());
            }
        });
        ThreadUtil.execAsync(() -> {
            try {
                tcpClient.connectAsync();
            } catch (Exception e) {
                log.error("[robot-client-comm] server bind error", e);
            }
        });
    }

}